/*
    user模块controller
 */
//数据库方法
const mysqlModel=require('../lib/users')
const baseModel=require('../lib/base')
//token登录凭证
const jwt=require('jsonwebtoken')
//数据库默认配置
const {config}=require('../config/default')
//错误处理
const ApiErrorNames=require('../error/ApiErrorNames')
//日期库
const moment = require('moment')
//获取登录ip
const getIp = require('../util/getIp')
//生成随机id
const { nanoid } = require('nanoid');
//md5加密密码
const md5 = require('md5');
//阿里云oss方法
const ali=require('../util/aliOSS_utils')

/*
 * 普通登录
 */
let login = async (ctx, next) => {
    const { body } = ctx.request
    try {
        const user = await mysqlModel.findUser(body.email)
        if (!user) {
            ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_NOT_EXIST)
            return
        }

        const email=body.email
        const {SALT, PASSWORD} = (await user)
        const pwd = SALT + md5(SALT + body.password)
        const current_role=await getUserRole(user.ID)
        // 匹配加密后的密码是否相等
        if (PASSWORD === pwd) {
            let updateInfo = {
                USER_ID: user.ID,
                IP: getIp.getUserIp(ctx.req),
                CREATED_BY: user.NICK_NAME,
                CREATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss'),
                UPDATED_BY: user.NICK_NAME,
                UPDATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss')
            }
            await mysqlModel
                .saveUserInfo(updateInfo)
                .then(() => {
                    let data = {
                        user: user.NICK_NAME,
                        role: current_role,
                        userId: user.ID,
                        email:email,
                        token_time:moment().format('YYYY-MM-DD HH:mm:ss'),
                        msg: '登录成功',
                        // 生成 token 返回给客户端
                        token: getToken({
                            user:user.ID,
                            user_name:user.NICK_NAME,
                            roleId:current_role,password:PASSWORD,
                        })
                    }
                    ctx.body = ApiErrorNames.getSuccessInfo(data)
                })
                .catch(err => {
                    ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.DATA_IS_WRONG)
                })
        } else {
            ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_LOGIN_ERROR)
        }
    } catch (error) {
        ApiErrorNames.errorCatch(error, ctx)
    }
}

/*
 * 获取用户信息
 */
let getUserList = async (ctx) => {
    const { page,pageNumber } = ctx.params
    try{
        const token=ctx.headers.authorization
        let payload
        if(token){
            //鉴权 只有管理员可以分配角色
            payload=await jwt.verify(token.split(' ')[1],config.secret)
            let {total}= await  mysqlModel.getTotal()
            if (payload.roleId==='1001'){
                let data={
                    //因为返回的是RowDataPacket 所以要解构
                    total,
                    items: await mysqlModel.getUserList(page,pageNumber)
                      .catch((err => {
                          ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.DATA_IS_WRONG)
                      }))
                }

                ctx.body=ApiErrorNames.getSuccessInfo(data)
            }
            else{
                ApiErrorNames.getErrorInfo(ApiErrorNames.USER_ACCOUNT_FORBIDDEN)
            }
        }
    }catch (e) {
        ApiErrorNames.errorCatch(e,ctx)
    }
}

/*
 * 通过ID获取用户信息
 */
let userInfoById = async (ctx) => {
    try {
        const token = ctx.headers.authorization
        let payload
        if (token) {
            await jwt.verify(token.split(' ')[1], config.secret) // 解密，获取payload
            const user = await mysqlModel.findUserInfoById(ctx.params.id)
            if (!user) {
                //找不到用户返回空对象
                ctx.body = ApiErrorNames.getSuccessInfo({})
            } else {
                ctx.body = ApiErrorNames.getSuccessInfo(user)
            }
        } else {
            ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.INVALID_TOKEN)
        }
    } catch (error) {
        ApiErrorNames.errorCatch(error, ctx)
    }
}

/*
 * 注册/管理员添加用户
 */
let register = async (ctx) => {
    const { body } = ctx.request
    try {
        const user = await mysqlModel.findUser(body.email)
        if (user) {
            ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_HAS_EXISTED)
            return
        }
        const userId = nanoid(12)
        const salt = nanoid(6)
        const pwd = salt + md5(salt + body.password)
        const role=body.roleId
        let info = [
            {
                ID: userId,
                NICK_NAME: body.nickname,
                SEX: 0,
                PASSWORD: pwd,
                SALT: salt,
                EMAIL: body.email,
                STATUS: '1',
                CREATED_BY: body.nickname,
                CREATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss'),
                UPDATED_BY: body.nickname,
                UPDATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss'),
            },
            {
                USER_ID: userId,
                ROLE_ID: role||'1003',
                STATUS: '1',
                CREATED_BY: body.nickname,
                CREATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss'),
                UPDATED_BY: body.nickname,
                UPDATED_TIME: moment().format('YYYY-MM-DD HH:mm:ss'),
            }
        ]
        await mysqlModel
            .register(info)
            .then(() => {
                ctx.body = ApiErrorNames.getSuccessInfo('创建用户成功')
                //创建用户成功后,新建属于这个用户的文件夹
                let client=ali.getClient()
                ali.createFolder(client,`${body.nickname}-${userId}`)
            })
            .catch(() => {
                ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.UNKNOWN_ERROR)
            })
    } catch (error) {
        ApiErrorNames.errorCatch(error, ctx)
    }
}
/*
  管理员删除用户
 */
let deleteUser=async (ctx,next)=>{
    try{
        const token=ctx.headers.authorization
        let payload
        let deleteId=ctx.params.id
        if(token){
            //鉴权 管理员可以删除所有人 普通用户只能删除/注销自己账户
            payload=await jwt.verify(token.split(' ')[1],config.secret)
            if (payload.user===deleteId||payload.roleId==='1001'){
                await mysqlModel.deleteUserById(deleteId)
                    .catch((err => {
                        ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.DATA_IS_WRONG)
                    }))
                ctx.body=ApiErrorNames.getSuccessInfo("删除成功!")
            }
            else{
                ApiErrorNames.getErrorInfo(ApiErrorNames.PERMISSION_NO_ACCESS)
            }
        }
    }catch (e) {
        ApiErrorNames.errorCatch(e,ctx)
    }
}
/*
 管理员给普通用户分配角色
 */
let allocateRole=async (ctx,next)=>{
    const { body } = ctx.request
    const {id,newRoleId}=body
    try{
        const token=ctx.headers.authorization
        let payload
        if(token){
            //鉴权 只有管理员可以分配角色
            payload=await jwt.verify(token.split(' ')[1],config.secret)
            if (payload.roleId==='1001'){
                await mysqlModel.allocateRole(id,newRoleId)
                    .catch((err => {
                        ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.DATA_IS_WRONG)
                    }))
                ctx.body=ApiErrorNames.getSuccessInfo("分配成功!")
            }
            else{
                ApiErrorNames.getErrorInfo(ApiErrorNames.USER_ACCOUNT_FORBIDDEN)
            }
        }
    }catch (e) {
        ApiErrorNames.errorCatch(e,ctx)
    }
}

/*
 * 退出登录
 */
let logout = async (ctx, next) => {
    try {
        ctx.body = ApiErrorNames.getSuccessInfo()
    } catch (error) {
        ApiErrorNames.errorCatch(error, ctx)
    }
}
/*
    token签发
 */
function getToken(payload={}){
    return jwt.sign(payload,config.secret,{expiresIn: '12h'})
}
/*
    获取当前操作用户的角色
 */
function getUserRole(id){
    return baseModel.getRoleByUserId(id)
}
module.exports={
    login,
    register,
    logout,
    deleteUser,
    userInfoById,
    getUserList,
    allocateRole
}
